package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	//testCopyLock() //不可复制
	//testRecursiveLock() //不可重入
	//testRecursiveDeadLock() //不可重入导致死锁
	testUnLock() //释放未加锁的 RWMutex

}

func testUnLock() {
	var mu sync.RWMutex
	defer mu.Unlock()
}

// main
//
//	@Description:不可复制 使用 go vet 检测， 命令  go vet xxx.go
func testCopyLock() {
	var c Counter
	c.Lock()
	defer c.Unlock()
	c.Count++
	copyLock(c) // 复制锁
}

// 这里Counter的参数是通过复制的方式传入的
func copyLock(c Counter) {
	c.Lock()
	defer c.Unlock()
	fmt.Println("in foo")
}

type Counter struct {
	sync.Mutex
	Count int
}

func testRecursiveLock() {
	var l sync.RWMutex
	first(&l)
}

func first(l *sync.RWMutex) {
	fmt.Println("in foo")
	l.Lock()
	second(l)
	l.Unlock()
}

func second(l *sync.RWMutex) {
	l.Lock()
	fmt.Println("in bar")
	l.Unlock()
}

func testRecursiveDeadLock() {
	var mu sync.RWMutex

	go func() {
		time.Sleep(200 * time.Millisecond)
		mu.Lock()

		fmt.Println("lock")
		time.Sleep(100 * time.Millisecond)
		mu.Unlock()
		fmt.Println("unlock")
	}()

	go func() {
		factorial(&mu, 10)
	}()

	select {}
}

func factorial(m *sync.RWMutex, n int) int {
	if n < 1 {
		return 0
	}

	fmt.Println("RLock")
	m.RLock()
	defer func() {
		fmt.Println("RUnlock")
		m.RUnlock()
	}()
	time.Sleep(100 * time.Millisecond)
	return factorial(m, n-1) * n //递归调用
}
